package model;

import java.util.Random;
import java.util.TreeMap;

import basics.ConversaoDeBases;

public class Memoria {

	private TreeMap<String, String> memoriaMap;

	// Tamanho da máximo da memória, 2^32 endereços
	protected final long TAMANHO = (long) Math.pow(2, 16) - 1;

	protected Memoria() {
		memoriaMap = new TreeMap<String, String>();

		inicializaMemoria();
	}

	protected boolean set(String endereco, String valor) {

		// Se excedeu tamanho da memória
		if (memoriaMap.get(endereco) == null)
			// aqui deve lançar uma exceção
			return false;
		else
			memoriaMap.put(endereco, valor);

		return true;
	}

	protected String get(String endereco) {
		return memoriaMap.get(endereco);
	}

	protected String getHalf(String endereco) {
		long endAux = ConversaoDeBases.binToDecUnsigned(endereco) + 1;

		return this.get(endereco) + this.get(ConversaoDeBases.DecToBin(endAux));
	}

	protected String getWord(String endereco) {
		String word = "";
		long endAux;

		word = this.get(endereco);

		endAux = ConversaoDeBases.binToDecUnsigned(endereco) + 1;
		word += this.get(ConversaoDeBases.DecToBin(endAux));

		endAux += 1;
		word += this.get(ConversaoDeBases.DecToBin(endAux));

		endAux += 1;
		word += this.get(ConversaoDeBases.DecToBin(endAux));

		return word;
	}

	protected void inicializaMemoria() {
		String end;
		String[] valor = new String[4];

		for (long i = 0; i < TAMANHO; i += 4) {

			// Incializar a memória está muito custoso!

			valor[0] = "00000000";
			valor[1] = "00000000";
			valor[2] = "00000000";
			valor[3] = "00000000";

			end = ConversaoDeBases.DecToBin(i);
			memoriaMap.put(end, valor[0]);

			end = ConversaoDeBases.DecToBin(i + 1);
			memoriaMap.put(end, valor[1]);

			end = ConversaoDeBases.DecToBin(i + 2);
			memoriaMap.put(end, valor[2]);

			end = ConversaoDeBases.DecToBin(i + 3);
			memoriaMap.put(end, valor[3]);
		}
	}

	@SuppressWarnings("unused")
	private void inicializaMemoriaRand() {
		String end;
		String[] valor = new String[4];
		String gen;

		Random rnd = new Random(System.currentTimeMillis()); // seed

		for (long i = 0; i < TAMANHO; i += 4) {

			gen = ConversaoDeBases.DecToBin(rnd.nextLong() % TAMANHO);

			// Incializar a memória está muito custoso!

			valor[0] = gen.substring(0, 8);
			valor[1] = gen.substring(8, 16);
			valor[2] = gen.substring(16, 24);
			valor[3] = gen.substring(24, 32);

			end = ConversaoDeBases.DecToBin(i);
			memoriaMap.put(end, valor[0]);

			end = ConversaoDeBases.DecToBin(i + 1);
			memoriaMap.put(end, valor[1]);

			end = ConversaoDeBases.DecToBin(i + 2);
			memoriaMap.put(end, valor[2]);

			end = ConversaoDeBases.DecToBin(i + 3);
			memoriaMap.put(end, valor[3]);
		}
	}

}